#pragma once
#include "Windows.h"

#include <string>
#include <string_view>
#include <xpack/xpack.h>

inline std::string utf16ToUtf8(std::wstring_view lpszSrc)
{
    std::string sResult;

    int nUTF8Len = WideCharToMultiByte(CP_UTF8, 0, lpszSrc.data(), -1, NULL, 0, NULL, NULL);
    sResult.resize(nUTF8Len - 1);
    WideCharToMultiByte(CP_UTF8, 0, lpszSrc.data(), -1, sResult.data(), nUTF8Len, NULL, NULL);

    return sResult;
}

inline std::wstring utf8ToUtf16(std::string_view utf8String)
{
    std::wstring sResult;

    int nUTF8Len = MultiByteToWideChar(CP_UTF8, 0, utf8String.data(), -1, NULL, NULL);
    sResult.resize(nUTF8Len - 1);
    MultiByteToWideChar(CP_UTF8, 0, utf8String.data(), -1, sResult.data(), nUTF8Len);

    return sResult;
}

namespace xpack
{
template <>
struct is_xpack_xtype<std::wstring>
{
    static bool const value = true;
};

template <class OBJ>
bool xpack_xtype_decode(OBJ &obj, const char *key, std::wstring &val, const Extend *ext)
{
    std::string str;
    if (!obj.decode(key, str, ext))
        return false;
    val = utf8ToUtf16(str);
    return true;
}

template <class OBJ>
bool xpack_xtype_encode(OBJ &obj, const char *key, const std::wstring &val, const Extend *ext)
{
    return obj.encode(key, utf16ToUtf8(val), ext);
}
} // namespace xpack
